From: Jonny Lamb Date: Thu, 7 Jul 2011 12:42:07 +0000 (+0100) Subject: telepathyClient: send typing notifications X-Git-Tag: archive/raspbian/50.5-1+rpi1~1^2~1013^2^2~8094 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=de348a4c494551fae64de72768b134c3d74fbb7d;p=gnome-shell.git telepathyClient: send typing notifications If we're typing we want to send composing. If we empty the entry we want to send active. If we're typing but don't type any more for COMPOSING_STOP_TIMEOUT seconds, we want to send paused. Simple. This behaviour was stolen from Empathy where it has won many awards. https://bugzilla.gnome.org/show_bug.cgi?id=650196 Based on patch from Jonny Lamb Signed-off-by: Alban Crequy --- diff --git a/js/ui/telepathyClient.js b/js/ui/telepathyClient.js index b916fac6f..e0bd8d063 100644 --- a/js/ui/telepathyClient.js +++ b/js/ui/telepathyClient.js @@ -24,6 +24,9 @@ const SCROLLBACK_IDLE_LENGTH = 5; // See Source._displayPendingMessages const SCROLLBACK_HISTORY_LINES = 10; +// See Notification._onEntryChanged +const COMPOSING_STOP_TIMEOUT = 5; + const NotificationDirection = { SENT: 'chat-sent', RECEIVED: 'chat-received' @@ -71,6 +74,7 @@ Client.prototype = { _init : function() { // channel path -> ChatSource this._chatSources = {}; + this._chatState = Tp.ChannelChatState.ACTIVE; // Set up a SimpleObserver, which will call _observeChannels whenever a // channel matching its filters is detected. @@ -458,6 +462,19 @@ ChatSource.prototype = { })); }, + setChatState: function(state) { + // We don't want to send COMPOSING every time a letter is typed into + // the entry. We send the state only when it changes. Telepathy/Empathy + // might change it behind our back if the user is using both + // gnome-shell's entry and the Empathy conversation window. We could + // keep track of it with the ChatStateChanged signal but it is good + // enough right now. + if (state != this._chatState) { + this._chatState = state; + this._channel.set_chat_state_async(state, null); + } + }, + _presenceChanged: function (contact, presence, status, message) { let msg, shouldNotify, title; @@ -547,6 +564,7 @@ ChatNotification.prototype = { this._responseEntry = new St.Entry({ style_class: 'chat-response', can_focus: true }); this._responseEntry.clutter_text.connect('activate', Lang.bind(this, this._onEntryActivated)); + this._responseEntry.clutter_text.connect('text-changed', Lang.bind(this, this._onEntryChanged)); this.setActionArea(this._responseEntry); this._oldMaxScrollAdjustment = 0; @@ -563,6 +581,7 @@ ChatNotification.prototype = { this._history = []; this._timestampTimeoutId = 0; + this._composingTimeoutId = 0; }, /** @@ -735,6 +754,39 @@ ChatNotification.prototype = { // see Source._messageSent this._responseEntry.set_text(''); this.source.respond(text); + }, + + _composingStopTimeout: function() { + this._composingTimeoutId = 0; + + this.source.setChatState(Tp.ChannelChatState.PAUSED); + + return false; + }, + + _onEntryChanged: function() { + let text = this._responseEntry.get_text(); + + // If we're typing, we want to send COMPOSING. + // If we empty the entry, we want to send ACTIVE. + // If we've stopped typing for COMPOSING_STOP_TIMEOUT + // seconds, we want to send PAUSED. + + // Remove composing timeout. + if (this._composingTimeoutId > 0) { + Mainloop.source_remove(this._composingTimeoutId); + this._composingTimeoutId = 0; + } + + if (text != '') { + this.source.setChatState(Tp.ChannelChatState.COMPOSING); + + this._composingTimeoutId = Mainloop.timeout_add_seconds( + COMPOSING_STOP_TIMEOUT, + Lang.bind(this, this._composingStopTimeout)); + } else { + this.source.setChatState(Tp.ChannelChatState.ACTIVE); + } } };